package com.ymx.darling.executor.statement;

import com.ymx.darling.bean.sql.BoundSql;
import com.ymx.darling.bean.sql.Statement;
import com.ymx.darling.exception.ExceptionFactory;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 批量插入的PreparedStatement处理器
 * @author 爱Java的小于
 */
public class InsertBatchPreparedStatement extends PreparedStatementHandler{

    public InsertBatchPreparedStatement(Statement statement) {
        super(statement);
    }

    /**
     * 批量插入时绑定参数不使用于此方法 所以进行重写
     * @param boundSql boundSql
     */
    @Override
    protected void bindParameters(BoundSql boundSql) {
    }


    /**
     * 批量插入时绑定参数不使用于此方法 所以进行重写
     * @param preparedStatement preparedStatement
     * @param params params
     */
    @Override
    public void setParameters(PreparedStatement preparedStatement, List<Object> params) {
    }


    @Override
    public int update(PreparedStatement preparedStatement)throws SQLException {
        Statement statement = this.statement;
        BoundSql boundSql = statement.getBoundSql();
        int insertBatchSize = statement.getInsertBatchSize();
        List<?> entityList = (List<?>) boundSql.getParameterObject();
        List<String> parameterMappings = boundSql.getParameterMappings();

        List<Object> errParameterList = new ArrayList<>();
        try {
            for (int i = 1, size = entityList.size(); i <= size; ++i) {
                Object entity = entityList.get(i - 1);
                BoundSql bs = new BoundSql(boundSql.getSql(), entity, parameterMappings);
                super.bindParameters(bs);// 进行参数绑定

                // 保存本批次的sql
                errParameterList.addAll(bs.getBindParameters());

                // 设置参数
                super.setParameters(preparedStatement, bs.getBindParameters());
                preparedStatement.addBatch();

                // 判断批量提交
                if (i % insertBatchSize == 0) {
                    errParameterList = new ArrayList<>();
                    preparedStatement.executeBatch();
                }
            }
            // 处理剩余的批量提交
            preparedStatement.executeBatch();
            // 进行主键的回填
            this.processAfterKeyGenerator(preparedStatement, statement.getKeyGenerator(), entityList);

            // 返回影响的行数
            return entityList.size();
        } catch (Exception exception) {
            throw ExceptionFactory.wrapSqlHandleException("批量插入时抛出异常", boundSql.getParameterBeforeBindSql(), errParameterList, exception);
        }
    }
}
